home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 January: Mac OS SDK / Dev.CD Jan 99 SDK1.toast / Development Kits / AppleScript / Development Tools / Sample Code / 7Edit 3.1 / Sources / SVEditUtils.c < prev    next >
Encoding:
Text File  |  1995-11-20  |  16.6 KB  |  626 lines  |  [TEXT/CWIE]

  1. // SVEditUtils.c
  2. //
  3. // 7Edit 3.1d1. Original version by Jon Lansdell and Nigel Humphreys.
  4. // 3.1 updates by Greg Sutton.
  5. // ©Apple Computer Inc 1995, all rights reserved.
  6.  
  7. /*
  8.     Changes for 3.1:
  9.     
  10.         12-Oct-95    : CW : Simplified FeatureIsImplemented routine.
  11.                            Added init of gHasDragManager flag in CheckEnvironment.
  12.  
  13. */
  14.  
  15.  
  16. #include <PLStringFuncs.h>
  17. #include <Events.h>
  18. #include <Traps.h>
  19. #include <Dialogs.h>
  20. #include <Fonts.h>
  21. #include <Packages.h>
  22. #include <ToolUtils.h>
  23. #include <AppleEvents.h>
  24. #include <CodeFragments.h>
  25. #include "SVEditUtils.h"
  26.  
  27. /**-----------------------------------------------------------------------
  28.         Name:             LesserOf
  29.         Purpose:        Returns the Lesser of two longints.
  30.     -----------------------------------------------------------------------**/
  31. #pragma segment Utils
  32.         
  33. pascal long LesserOf(long A, long B)
  34.  {
  35.    if (A<B)
  36.        return(A);
  37.      else
  38.        return(B);
  39.  }   /*LesserOf*/
  40.             
  41. /**-----------------------------------------------------------------------
  42.         Name:             GreaterOf
  43.         Purpose:        Returns the Greater of two longints.
  44.     -----------------------------------------------------------------------**/
  45.     
  46. #pragma segment Utils
  47.         
  48. pascal long GreaterOf(long A, long B)
  49.  {
  50.    if (A>B)
  51.        return(A);
  52.      else
  53.        return(B);
  54.  }  /*GreaterOf*/
  55.             
  56. /**-----------------------------------------------------------------------
  57.         Name:             ShowError
  58.         Purpose:        Reports an error to the user as both string and number.
  59.     -----------------------------------------------------------------------**/
  60. #pragma segment Utils
  61.         
  62. pascal void ShowError(Str255  theError,
  63.                                           long    theErrorCode)
  64. {
  65.    short     alertResult;
  66.    Str255    theString;
  67.      OSErr     myErr;
  68.      
  69.      myErr = AEInteractWithUser(kAEDefaultTimeout, nil,nil);
  70.      
  71.      if (myErr == noErr)
  72.        {
  73.              SetCursor(&qd.arrow);
  74.              NumToString(theErrorCode, theString);
  75.              ParamText(theError, theString, (unsigned char *)"", (unsigned char *)"");
  76.              alertResult = Alert(300, nil);
  77.          }
  78. } /* ShowError */
  79.  
  80. /**-----------------------------------------------------------------------
  81.         Name:             Ours
  82.         Purpose:        Checks the frontmost window belongs to the app.
  83.     -----------------------------------------------------------------------**/
  84. #pragma segment Utils        
  85.     
  86. pascal Boolean Ours(WindowPtr aWindow)
  87.  {
  88.         if (aWindow)
  89.             if (((WindowPeek)aWindow)->windowKind == zoomDocProc)
  90.                 return(true);
  91.         return(false);
  92. } /* Ours */
  93.  
  94. /**-----------------------------------------------------------------------
  95.         Name:             SetShortMenus
  96.         Purpose:        Cuts the menus down to a minimum - Apple File Edit.
  97.                                 Greys out the unavailable options - used when no docs open
  98.     -----------------------------------------------------------------------**/
  99. #pragma segment Utils        
  100.  
  101. pascal void SetShortMenus()
  102.     DeleteMenu(mfontID);
  103.     DeleteMenu(sizeID);
  104.     DeleteMenu(styleID);
  105.  
  106.     DisableItem(myMenus[fileM], fmClose);
  107.     DisableItem(myMenus[fileM], fmSave);
  108.     DisableItem(myMenus[fileM], fmSaveAs);
  109.     DisableItem(myMenus[fileM], fmRevert);
  110.     DisableItem(myMenus[fileM], fmPageSetUp);
  111.  
  112.     if (gGXIsPresent)
  113.     {
  114.         DisableItem(myMenus[fileM], fmPrint);
  115.         DisableItem(myMenus[fileM], fmPrintOne );
  116.     }
  117.     else
  118.         DisableItem(myMenus[fileM], fmNoGXPrint);
  119.  
  120.     /* now the unnecessary items on the edit menu */
  121.                 
  122.     DisableItem(myMenus[editM], undoCommand);
  123.     DisableItem(myMenus[editM], cutCommand);
  124.     DisableItem(myMenus[editM], copyCommand);
  125.     DisableItem(myMenus[editM], clearCommand);
  126.     DisableItem(myMenus[editM], pasteCommand);
  127.     DisableItem(myMenus[editM], selectAllCommand);
  128.  
  129.     DrawMenuBar();
  130. }  /* SetShortMenus */
  131.  
  132. /**-----------------------------------------------------------------------
  133.         Name:             SetLongMenus
  134.         Purpose:        Reinstates the full menu bar - called when first document
  135.                     opened.
  136.     -----------------------------------------------------------------------**/
  137. #pragma segment Utils        
  138.  
  139. pascal void SetLongMenus()
  140.   {
  141.         InsertMenu(myMenus[fontM], 0);
  142.         InsertMenu(myMenus[sizeM], 0);
  143.         InsertMenu(myMenus[styleM], 0);
  144.  
  145.         EnableItem(myMenus[fileM], fmClose);
  146.         EnableItem(myMenus[fileM], fmSave);
  147.         EnableItem(myMenus[fileM], fmSaveAs);
  148.         EnableItem(myMenus[fileM], fmRevert);
  149.         EnableItem(myMenus[fileM], fmPageSetUp);
  150.  
  151.         if (gGXIsPresent)
  152.         {
  153.             EnableItem(myMenus[fileM],  fmPrint );
  154.             EnableItem(myMenus[fileM],  fmPrintOne );
  155.         }
  156.         else
  157.             EnableItem(myMenus[fileM], fmNoGXPrint );
  158.  
  159.         /* now the necessary items on the edit menu -
  160.             many other items fixed on each pass thru the main event
  161.             loop or before the window pulled down
  162.         */
  163.         
  164.         EnableItem(myMenus[editM], selectAllCommand);
  165.  
  166.         DrawMenuBar();
  167.     }  /* SetLongMenus */
  168.  
  169. /**-----------------------------------------------------------------------
  170.         Name:             SetStyleMenu
  171.         Purpose:        Sets the style menu checking to reflect the style of the
  172.                     first character of the current selection in the given
  173.                                 document.
  174.     -----------------------------------------------------------------------**/
  175. #pragma segment Utils        
  176.         
  177. pascal void SetStyleMenu(DPtr theDoc)
  178.   {
  179.     TextStyle        theTStyle;
  180.         short       contMode;
  181.         short       i;
  182.         
  183.         contMode = doFace;
  184.         
  185.         TEContinuousStyle(&contMode,&theTStyle,theDoc->theText);
  186.         
  187.         if ((contMode & doFace) != 0)
  188.             {
  189.                 CheckItem(myMenus[styleM], cPlain,     (theTStyle.tsFace == 0));
  190.                 CheckItem(myMenus[styleM], cBold,      (bold      & theTStyle.tsFace));
  191.                 CheckItem(myMenus[styleM], cItalic,    (italic    & theTStyle.tsFace));
  192.                 CheckItem(myMenus[styleM], cUnderline, (underline & theTStyle.tsFace));
  193.                 CheckItem(myMenus[styleM], cOutline,   (outline   & theTStyle.tsFace));
  194.                 CheckItem(myMenus[styleM], cShadow,    (shadow    & theTStyle.tsFace));
  195.                 CheckItem(myMenus[styleM], cCondense,  (condense  & theTStyle.tsFace));
  196.                 CheckItem(myMenus[styleM], cExtend,    (extend    & theTStyle.tsFace));
  197.           }
  198.         else
  199.             for (i=cPlain; i<= cExtend; i++)
  200.                 CheckItem(myMenus[styleM], i,     false);
  201.   }
  202.  
  203. /**-----------------------------------------------------------------------
  204.     Name:       SetSizeMenu
  205.     Purpose:    Outline all the items if the current font is an
  206.                 outline font. Check the size of the current selection
  207.   -----------------------------------------------------------------------**/
  208. #pragma segment Utils        
  209.  
  210. pascal void SetSizeMenu(DPtr theDoc)
  211.   {
  212.       short             i;
  213.         short                aSize;
  214.         short                max;
  215.     long                 theSize;
  216.     Str255        name;
  217.     Boolean       sizeinMenu;
  218.     Boolean       oldState;
  219.     Point         numer;
  220.     TextStyle        theStyle;
  221.         TEHandle    myText;
  222.         short       contMode;
  223.       
  224.     numer.h = 1;
  225.     numer.v = 1;
  226.  
  227.     myText = theDoc->theText;
  228.         
  229.         contMode = doSize+doFont;
  230.         
  231.         TEContinuousStyle(&contMode,&theStyle,theDoc->theText);
  232.         
  233.     sizeinMenu = false;
  234.     max = CountMItems(myMenus[sizeM]);
  235.         for (i = 1; i <= max - 5; i++)
  236.       {
  237.                 GetItem(myMenus[sizeM], i, name);
  238.                 StringToNum(name, &theSize);
  239.                 aSize = (short)theSize;
  240.  
  241.                 if (RealFont(theStyle.tsFont, aSize) && (contMode & doFont) != 0) // there is only one font and this size exists
  242.                     SetItemStyle(myMenus[sizeM], i, outline);
  243.                 else
  244.                     SetItemStyle(myMenus[sizeM], i, 0);
  245.  
  246.                 if ((aSize == theStyle.tsSize) && (contMode & doSize) != 0)
  247.                     {
  248.                         sizeinMenu = true;
  249.                         CheckItem(myMenus[sizeM], i, true);
  250.                     }
  251.                 else
  252.                     CheckItem(myMenus[sizeM], i, false);
  253.             }
  254.         
  255.             /*
  256.                 if it's not a size in the menu,and there is only one size in the
  257.               selection range check the other item
  258.             */
  259.             
  260.             if (!sizeinMenu && (contMode & doSize) != 0)
  261.               CheckItem(myMenus[sizeM], max, true);
  262.             else
  263.                 CheckItem(myMenus[sizeM], max, false);
  264.  
  265.             /*if this is an outline font, set the rest of the items to outline style*/
  266.             /*RealFont will ensure that the sizes are outlined*/
  267.  
  268.             oldState = GetOutlinePreferred();
  269.             SetOutlinePreferred(true);
  270.             for (i = max-4; i <= max; i++)
  271.                 {
  272.                     if (IsOutline(numer, numer) && (contMode & doFont)!= 0)
  273.                         SetItemStyle(myMenus[sizeM], i, outline);
  274.                     else
  275.                         SetItemStyle(myMenus[sizeM], i, 0);
  276.                 }
  277.                 
  278.             SetOutlinePreferred(oldState);
  279.     }
  280.  
  281. /**-----------------------------------------------------------------------
  282.     Name:       SetFontMenu
  283.     Purpose:    Set the font menu according to the state of
  284.                                 current selection of the supplied document.
  285.   -----------------------------------------------------------------------**/
  286. #pragma segment Utils
  287.         
  288. pascal void SetFontMenu(DPtr theDoc)
  289.   {
  290.     MenuHandle        theMHandle;
  291.     short         theNumber;
  292.     short         i;
  293.     short                max;
  294.     Str255        name;
  295.     TextStyle     theStyle;
  296.         short         contMode;
  297.  
  298.         theMHandle = GetMHandle(mfontID);
  299.  
  300.         if (gFontMItem)
  301.       CheckItem(theMHandle, gFontMItem, false);
  302.             
  303.         max = CountMItems(theMHandle);
  304.  
  305.         contMode = doFont;
  306.         TEContinuousStyle(&contMode,&theStyle,theDoc->theText);
  307.  
  308.         gFontMItem = 0;
  309.         
  310.     if (contMode & doFont)
  311.             for (i=1; i<=max; i++)
  312.                 {
  313.                     GetItem(theMHandle, i, name);
  314.                     GetFNum(name, &theNumber);
  315.                     if (theNumber == theStyle.tsFont)
  316.                         gFontMItem = i;
  317.                 }
  318.  
  319.     if (gFontMItem)
  320.       CheckItem(theMHandle, gFontMItem, true);
  321.             
  322.         SetSizeMenu(theDoc);
  323.         SetStyleMenu(theDoc);
  324.     }
  325.  
  326. /**-----------------------------------------------------------------------
  327.     Name:       GetTempFileName
  328.     Purpose:    Fills newstring with a temporary file name.
  329.   -----------------------------------------------------------------------**/
  330.  
  331. #pragma segment Utils
  332.  
  333. pascal void GetTempFileName(DPtr aDoc,
  334.                             Str255 newString)
  335.  
  336.     {
  337.        Str255        s;
  338.      Str255        fileName;
  339.  
  340.         if (aDoc->everSaved == false)
  341.           PLstrcpy(fileName, (unsigned char *)"\pTEXTra");
  342.         else
  343.             PLstrcpy(fileName, aDoc->theFileName);
  344.  
  345.     /*generate a unique(ish) temporary filename*/
  346.         
  347.         if (fileName[0] > 21)
  348.           fileName[0] = 21;
  349.                 
  350.         NumToString(TickCount(), s);
  351.         
  352.         PLstrcat(fileName, s);
  353.         
  354.         PLstrcpy(newString,fileName);
  355.     }
  356.  
  357. /**-----------------------------------------------------------------------
  358.     Name:       SetText
  359.     Purpose:    Sets the text of the supplied itemNo in aDialog to 
  360.                                 theString and select it.
  361.   -----------------------------------------------------------------------**/
  362.  
  363. #pragma segment Utils
  364.  
  365. pascal void SetText(DialogPtr aDialog,
  366.                     short     itemNo,
  367.                     Str255    theString)
  368.   {
  369.     Handle      itemHandle;
  370.     Rect        box;
  371.     short       kind;
  372.     TEHandle    theTEHandle;
  373.  
  374.         GetDItem(aDialog, itemNo, &kind, &itemHandle, &box);
  375.         SetIText(itemHandle, theString);
  376.         
  377.         theTEHandle = ((DialogPeek)aDialog)->textH;
  378.  
  379.         /*set all the text to be selected*/
  380.         if (theTEHandle)
  381.             TESetSelect(0, 255, theTEHandle);
  382.     }
  383.             
  384. /**-----------------------------------------------------------------------
  385.     Name:       RetrieveText
  386.     Purpose:    Returns the text of anItem in aDialog in aString.
  387.   -----------------------------------------------------------------------**/
  388.  
  389. #pragma segment Utils
  390.  
  391. pascal void RetrieveText(DialogPtr aDialog,
  392.                                                short     anItem,
  393.                                                Str255    aString)
  394.   {
  395.      short      kind;
  396.      Rect       box;
  397.      Handle     itemHandle;
  398.  
  399.          GetDItem(aDialog, anItem, &kind, &itemHandle, &box);
  400.          GetIText(itemHandle, aString);
  401.   }
  402.  
  403. /**-----------------------------------------------------------------------
  404.     Name:       DrawDefaultOutline
  405.     Purpose:    Draws an outline around theItem.
  406.                                 Called as a useritem Proc by the dialog manager.
  407.                                 To use place a useritem over the default item in the
  408.                                 dialog and install the address of this proc as the item
  409.                                 handle.
  410.   -----------------------------------------------------------------------**/
  411.  
  412. #pragma segment Utils
  413.  
  414. pascal void DrawDefaultOutline(DialogPtr theDialog, short theItem)
  415.   {
  416.       short       kind;
  417.     Handle      itemHandle;
  418.     Rect        box;
  419.                 
  420.     GetDItem(theDialog, theItem, &kind, &itemHandle, &box);
  421.     PenSize(3, 3);
  422.     InsetRect(&box, - 4, - 4);
  423.     FrameRoundRect(&box, 16, 16);
  424.     PenNormal();
  425.         
  426.     }  /* DrawDefaultOutline */
  427.             
  428. /**-----------------------------------------------------------------------
  429.     Name:       AdornDefaultButton
  430.     Purpose:    Installs DrawDefaultOutline as the useritem proc
  431.                     for the given item.
  432.   -----------------------------------------------------------------------**/
  433.  
  434. #pragma segment Utils
  435.         
  436. pascal void AdornDefaultButton(DialogPtr theDialog,short theItem)
  437.   {
  438.       short       kind;
  439.     Handle      itemHandle;
  440.     Rect        box;
  441.  
  442.         GetDItem(theDialog, theItem, &kind, &itemHandle, &box);
  443.         SetDItem(theDialog, theItem, kind, (Handle)gDefaultButtonUPP, &box);
  444.   }
  445.  
  446.     /*-------  Determining of Gestalt is available ---------------*/
  447.     /*The following routines come from the Inside Mac VI recommendations*/
  448.     /*about how to find if a trap is available*/
  449.          /*
  450.             The glue for Gestalt will be in MPW 3.2, so if it is available we will also
  451.              need to check the system version
  452.         */
  453.  
  454. pascal void GetRectOfDialogItem(DialogPtr theDialog, short theItem, Rect *theRect)
  455.     {
  456.       short       kind;
  457.     Handle      itemHandle;
  458.         
  459.         GetDItem(theDialog, theItem, &kind, &itemHandle, theRect);
  460.     }
  461.  
  462. #pragma segment Utils
  463.  
  464. pascal short NumToolboxTraps(void)
  465.   {
  466.         if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
  467.             return(0x200);
  468.         else
  469.             return(0x400);
  470.     }
  471.  
  472. #pragma segment Utils
  473.  
  474. #define TrapMask  0x0800
  475.  
  476. pascal TrapType GetTrapType(short theTrap)
  477.   {
  478.         if ((theTrap & TrapMask) > 0)
  479.             return(ToolTrap);
  480.         else
  481.             return(OSTrap);
  482.     }
  483.  
  484. #pragma segment Utils
  485.  
  486. pascal Boolean TrapAvailable(short theTrap)
  487.   {
  488.         TrapType  tType;
  489.  
  490.         tType = GetTrapType(theTrap);
  491.         if (tType == ToolTrap)
  492.             {
  493.                 theTrap = theTrap & 0x07FF;
  494.                 if (theTrap >= NumToolboxTraps())
  495.                     theTrap = _Unimplemented;
  496.             }
  497.         return(NGetTrapAddress(theTrap, tType) != NGetTrapAddress(_Unimplemented,ToolTrap));
  498.     }
  499.  
  500. #pragma segment Utils
  501.  
  502. #define _Gestalt 0xA1AD
  503.  
  504. pascal Boolean GestaltAvailable()
  505.   {
  506.         return(TrapAvailable(_Gestalt));
  507.     }
  508.  
  509. /**------  FeatureIsImplemented    ------------**/
  510. /*This is called to use Gestalt to determine if a feature is implemented.
  511.  This applies to only those referenced by OSType*/
  512.  
  513. #pragma segment Utils
  514.  
  515.  
  516. pascal Boolean FeatureIsImplemented ( OSType theFeature, short theTestBit )
  517. {
  518.     OSErr     err;
  519.     long      result;
  520.  
  521.     err = Gestalt ( theFeature, &result );
  522.     return (err == noErr && (result & (1L << theTestBit)));
  523.     
  524. }
  525.  
  526.  
  527.  
  528.  
  529. #pragma segment Utils
  530.  
  531. pascal Boolean CheckEnvironment()
  532.   {
  533.         /*
  534.          first determine of Gestalt is available- if it isn't exit
  535.          as we only run under 7.0.  It could it present in 6.04 - so we need
  536.          to do some further checks for important features
  537.         */
  538.  
  539.         gGestaltAvailable = GestaltAvailable();
  540.         
  541.         if (!gGestaltAvailable)
  542.             return(false);
  543.  
  544.     /*first check if the Edition Manager is present*/
  545.                 
  546.     gEditionManagerImplemented = FeatureIsImplemented(gestaltEditionMgrAttr,
  547.                                                                                                           gestaltEditionMgrPresent);
  548.  
  549.         /*and for good measure- the Alias manager*/
  550.                 
  551.         gAliasManagerImplemented  = FeatureIsImplemented(gestaltAliasMgrAttr,
  552.                                                                                                          gestaltAliasMgrPresent);
  553.             
  554.         /*check for the AppleEvents manager - we certainly can't work without it*/
  555.         
  556.         gAppleEventsImplemented   = FeatureIsImplemented(gestaltAppleEventsAttr,
  557.                                                                                                          gestaltAppleEventsPresent);
  558.         
  559.         /*check if recording is implemented*/
  560.         
  561.         gRecordingImplemented   = FeatureIsImplemented(gestaltAppleEventsAttr,1);
  562.             
  563.         /*check for the Outline fonts*/
  564.         
  565.         gOutlineFontsImplemented  = FeatureIsImplemented(gestaltFontMgrAttr,
  566.                                                                                                          gestaltOutlineFonts);
  567.         
  568.     
  569.     // We would also like the Drag Manager
  570.     gHasDragManager = FeatureIsImplemented ( gestaltDragMgrAttr, gestaltDragMgrPresent );
  571.     
  572.     // It isn't enough to use Gestalt because we may not have sucessfully linked
  573.     // to the DragLib shared library. So, we also need to test one of the symbols
  574.     // against kUnresolvedSymbol to make sure we have a valid connection to it.
  575.     
  576. #if GENERATINGCFM
  577.     if ( gHasDragManager )
  578.         gHasDragManager = (InstallTrackingHandler != (void*) kUnresolvedSymbolAddress);
  579. #endif
  580.  
  581.  
  582.         return (gEditionManagerImplemented &&
  583.                         gAliasManagerImplemented   &&
  584.                         gAppleEventsImplemented    &&
  585.                         gOutlineFontsImplemented);
  586.                                 
  587.     }  /* CheckEnvironment */
  588.             
  589.     /*
  590.         DoPageSetup returns true if the page setup of the document is altered
  591.     */
  592.     
  593.     pascal Boolean DoPageSetup(DPtr theDoc)
  594.         {
  595.             Boolean result = false;
  596.                 
  597.                 if (!gGXIsPresent)
  598.                     if (theDoc)
  599.                         {
  600.                             PrOpen();
  601.                             result =  PrStlDialog(theDoc->thePrintSetup);
  602.                             PrClose();
  603.                         }
  604.                     
  605.                 return(result);
  606.         }  /* DoPageSetup */
  607.  
  608. /*
  609.     Name:    CtrlKeyPressed
  610.     Purpose: Returns true if control key pressed during event
  611. */
  612. pascal Boolean CtrlKeyPressed(const EventRecord *theEvent)
  613.     {
  614.         return((theEvent->modifiers & controlKey) != 0);
  615.     }
  616.     
  617. /*
  618.     Name:    OptionKeyPressed
  619.     Purpose: Returns true if option key pressed during event
  620. */
  621. pascal Boolean OptionKeyPressed(const EventRecord *theEvent)
  622.     {
  623.         return((theEvent->modifiers & optionKey) != 0);
  624.     }
  625.